/**
 * 分类细分识别服务
 * 
 * 功能：从交易备注中识别更细粒度的子类别
 * 
 * @author 预算管理系统开发团队
 * @date 2025-10-15
 */

// ==================== 子类别映射表 ====================

/**
 * 分类细分规则
 * 每个大类包含多个子类别，每个子类别定义关键词匹配规则
 */
const SUBCATEGORY_RULES = {
  // 餐饮细分
  '餐饮': {
    '食堂': ['食堂', '餐厅', '餐饮', '一楼', '二楼', '三楼', '东区', '西区', '南区', '北区', '学生', '教工'],
    '外卖': ['外卖', '美团', '饿了么', '点外卖', '外送', '配送'],
    '快餐': ['麦当劳', '肯德基', 'KFC', '汉堡王', '德克士', '必胜客', '快餐'],
    '奶茶饮品': ['奶茶', '茶饮', '咖啡', '星巴克', '瑞幸', '蜜雪冰城', '喜茶', '奈雪', 'coco', '一点点', '古茗', '书亦烧仙草', '茶百道'],
    '小吃零食': ['零食', '小吃', '炒粉', '炒饭', '炸鸡', '烤串', '煎饼', '包子', '馒头', '粥', '烧烤', '麻辣烫'],
    '正餐': ['餐馆', '酒楼', '饭店', '餐厅', '火锅', '自助', '西餐', '日料', '烤肉', '海鲜', '川菜', '湘菜', '粤菜'],
    '超市食品': ['超市', '便利店', '711', '全家', '罗森', '永辉', '沃尔玛', '家乐福', '大润发', '华润']
  },

  // 购物细分
  '购物': {
    '电商平台': ['淘宝', '天猫', '京东', '拼多多', '唯品会', '苏宁', '当当', '亚马逊', '网购', '在线购物'],
    '超市': ['超市', '便利店', '711', '全家', '罗森', '永辉', '沃尔玛', '家乐福', '大润发', '华润', '物美', '卜蜂莲花'],
    '服饰': ['衣服', '鞋', '裤子', '裙子', '外套', '优衣库', 'ZARA', 'HM', '服装', '运动服', '内衣'],
    '日用品': ['日用', '洗发', '沐浴', '牙膏', '纸巾', '洗衣', '清洁', '毛巾', '拖鞋'],
    '化妆品': ['化妆', '护肤', '面膜', '口红', '粉底', '眉笔', '美妆', '护肤品'],
    '电子产品': ['手机', '电脑', '平板', 'iPad', 'iPhone', '耳机', '充电', '数码', '电子', '键盘', '鼠标', '显示器'],
    '书籍文具': ['书', '笔', '本子', '文具', '书店', '图书', '教材', '教辅', '文具店']
  },

  // 交通细分
  '交通': {
    '公交地铁': ['公交', '地铁', '公共交通', '交通卡', '一卡通', '羊城通', '深圳通'],
    '打车': ['滴滴', '打车', '出租车', '网约车', '专车', '快车', '顺风车', 'Uber', '曹操'],
    '共享单车': ['共享单车', '单车', '自行车', '摩拜', '哈啰', '美团单车', '青桔'],
    '火车高铁': ['火车', '高铁', '动车', '12306', '铁路', '车票'],
    '飞机': ['机票', '航空', '飞机', '航班', '登机'],
    '其他交通': ['加油', '停车', '过路费', '高速', '违章', '保养', '维修']
  },

  // 娱乐细分
  '娱乐': {
    '视频会员': ['视频', '会员', '爱奇艺', '腾讯视频', '优酷', 'B站', '芒果TV', 'Netflix'],
    '音乐': ['音乐', 'QQ音乐', '网易云', '酷狗', '酷我', 'Spotify'],
    '游戏': ['游戏', '充值', '皮肤', '装备', '王者', '和平精英', '原神', 'Steam'],
    '电影': ['电影', '影院', '电影票', '观影', '院线'],
    'KTV': ['KTV', 'K歌', '唱歌', '点歌'],
    '运动': ['健身', '游泳', '球类', '羽毛球', '篮球', '足球', '瑜伽', '跑步'],
    '其他娱乐': ['旅游', '景点', '门票', '展览', '演出', '音乐会']
  },

  // 生活服务细分
  '生活': {
    '通讯': ['手机', '话费', '流量', '套餐', '充值', '中国移动', '中国联通', '中国电信'],
    '水电燃气': ['水费', '电费', '燃气', '物业', '暖气'],
    '房租': ['房租', '租金', '房费', '住宿'],
    '医疗': ['医院', '药店', '药房', '看病', '体检', '挂号', '医疗', '药品'],
    '理发': ['理发', '美发', '剪发', '染发', '烫发', '美容'],
    '快递': ['快递', '邮费', '运费', '顺丰', '圆通', '中通', '申通', '韵达'],
    '其他服务': ['洗衣', '维修', '清洁', '保洁', '搬家']
  },

  // 学习细分
  '学习': {
    '课程培训': ['培训', '课程', '补习', '辅导', '教育', '学习', '网课'],
    '教材资料': ['教材', '资料', '书', '教辅', '试卷'],
    '考试报名': ['报名', '考试', '证书', '考证', '四六级', '雅思', '托福'],
    '技能学习': ['技能', '证书', '驾校', '驾照', '编程', '设计']
  },

  // 转账与社交细分
  '转账': {
    '红包': ['红包', '发红包', '抢红包'],
    '转账': ['转账', '转给', '收款'],
    '还款': ['还款', '借款', '欠款', '借钱'],
    '分摊': ['AA', '分摊', '平摊', '收款']
  }
};

/**
 * 商户关键词提取规则
 * 用于从备注中提取商户名称
 */
const MERCHANT_PATTERNS = [
  // 电商平台
  /淘宝|天猫|京东|拼多多|唯品会|苏宁|当当/,
  // 超市便利店
  /711|全家|罗森|永辉|沃尔玛|家乐福|大润发|华润|物美/,
  // 餐饮
  /麦当劳|肯德基|KFC|汉堡王|必胜客|星巴克|瑞幸|蜜雪冰城|喜茶|奈雪|海底捞|外婆家|西贝/,
  // 食堂
  /东区.*?食堂|西区.*?食堂|南区.*?食堂|北区.*?食堂|.*?食堂|.*?餐厅|.*?餐饮/,
  // 出行
  /滴滴|美团|哈啰|摩拜|青桔/,
  // 其他
  /.*?专营店|.*?旗舰店|.*?店|.*?超市|.*?商场/
];

// ==================== 核心功能函数 ====================

/**
 * 识别子类别
 * @param {string} category - 主类别
 * @param {string} remark - 交易备注
 * @returns {string|null} - 识别到的子类别，未识别返回null
 */
function identifySubcategory(category, remark) {
  if (!remark || !category) return null;

  const remarkLower = remark.toLowerCase();
  const rules = SUBCATEGORY_RULES[category];
  
  if (!rules) return null;

  // 遍历子类别规则
  for (const [subcategory, keywords] of Object.entries(rules)) {
    for (const keyword of keywords) {
      if (remarkLower.includes(keyword.toLowerCase())) {
        return subcategory;
      }
    }
  }

  return null;
}

/**
 * 提取商户名称
 * @param {string} remark - 交易备注
 * @returns {string|null} - 提取到的商户名称
 */
function extractMerchant(remark) {
  if (!remark) return null;

  // 尝试用正则提取
  for (const pattern of MERCHANT_PATTERNS) {
    const match = remark.match(pattern);
    if (match) {
      return match[0];
    }
  }

  // 如果没有匹配到，尝试从备注中提取前面的关键词
  // 例如："东区一楼食堂 大众快餐" -> "东区一楼食堂"
  const parts = remark.split(/[，,、\s]/);
  if (parts.length > 0 && parts[0].length > 1 && parts[0].length <= 20) {
    return parts[0];
  }

  return null;
}

/**
 * 批量分析记录的子类别和商户
 * @param {Array} records - 记录数组 [{category, remark}, ...]
 * @returns {Array} - 增强后的记录数组 [{category, subcategory, merchant, ...}, ...]
 */
function enhanceRecords(records) {
  return records.map(record => {
    const subcategory = identifySubcategory(record.category, record.remark);
    const merchant = extractMerchant(record.remark);
    
    return {
      ...record,
      subcategory: subcategory || '其他',
      merchant: merchant || record.remark || '未知'
    };
  });
}

/**
 * 统计子类别分布
 * @param {Array} records - 记录数组
 * @returns {Object} - 子类别统计 {category: {subcategory: {count, amount}}}
 */
function analyzeSubcategoryDistribution(records) {
  const enhancedRecords = enhanceRecords(records);
  const stats = {};

  for (const record of enhancedRecords) {
    const { category, subcategory, amount } = record;
    
    if (!stats[category]) {
      stats[category] = {};
    }
    
    if (!stats[category][subcategory]) {
      stats[category][subcategory] = { count: 0, amount: 0 };
    }
    
    stats[category][subcategory].count++;
    stats[category][subcategory].amount += parseFloat(amount || 0);
  }

  return stats;
}

/**
 * 统计商户频率（Top N）
 * @param {Array} records - 记录数组
 * @param {number} topN - 返回前N个商户
 * @returns {Array} - 商户统计 [{merchant, count, amount}, ...]
 */
function analyzeTopMerchants(records, topN = 10) {
  const enhancedRecords = enhanceRecords(records);
  const merchantStats = {};

  for (const record of enhancedRecords) {
    const { merchant, amount } = record;
    
    if (!merchant || merchant === '未知') continue;
    
    if (!merchantStats[merchant]) {
      merchantStats[merchant] = { merchant, count: 0, amount: 0 };
    }
    
    merchantStats[merchant].count++;
    merchantStats[merchant].amount += parseFloat(amount || 0);
  }

  // 转换为数组并排序
  return Object.values(merchantStats)
    .sort((a, b) => {
      // 先按次数排序，次数相同按金额排序
      if (b.count !== a.count) return b.count - a.count;
      return b.amount - a.amount;
    })
    .slice(0, topN);
}

// ==================== 导出 ====================

module.exports = {
  identifySubcategory,
  extractMerchant,
  enhanceRecords,
  analyzeSubcategoryDistribution,
  analyzeTopMerchants,
  SUBCATEGORY_RULES
};

